package cn.wzl.tanks;

import cn.wzl.tanks.abstractfactory.*;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

/**
 * @author weiZhiLin
 * @version 1.0
 * @date 2021/5/9 15:39
 */
public class TankFrame extends Frame {
    //factory
    BaseFactory bf = new YellowFactory();
    public static final int GAME_WIDTH = PropertyMrg.getIntegerValue("tfWidth");
    public static final int GAME_HEIGHT = PropertyMrg.getIntegerValue("tfHeight");

    public int x = 100, y = 100;
    // 坦克
    public BaseTank t = bf.creatTank(x, y, Dir.DOWN, this, Group.GOOD);
    // 子弹
    public List<BaseBullet> bList = new ArrayList<>();
    // 敌方坦克
    public static List<BaseTank> badTanks = new ArrayList<>();
    // boom
    public List<BaseBoom> booms = new ArrayList<>();


    public TankFrame() {
        setVisible(true);
        setSize(GAME_WIDTH, GAME_HEIGHT);
        setTitle("坦克大战");
        this.addKeyListener(new KeyMapListener());
        // bad tanks
        for (int i = 0; i < 5; i++) {
            BaseTank bad = bf.creatTank(30 + i * 60, 30, Dir.DOWN, this, Group.BAD);
            bad.setMoving(true);
            badTanks.add(bad);
        }
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }

    // 绘制
    @Override
    public void paint(Graphics g) {
        // 敌方坦克绘制
        for (int i = 0; i < badTanks.size(); i++) {
            badTanks.get(i).paint(g);
        }
        // 坦克绘制
        t.paint(g);
        // 子弹绘制, bList.size() 实时计算 不会报错，适用迭代器时 删除子弹回报错
        for (int i = 0; i < bList.size(); i++) {
            bList.get(i).paint(g);
        }

        // 碰撞计算
        for (int i = 0; i < bList.size(); i++) {
            for (int k = 0; k < badTanks.size(); k++) {
                bList.get(i).checkCash(badTanks.get(k));
            }
        }
        // 爆炸效果
        for (int i = 0; i < booms.size(); i++) {
            booms.get(i).paint(g);
        }

    }

    // 键盘监听内部类
    class KeyMapListener extends KeyAdapter {
        // 上下左右四个键位，代表是否被按下
        boolean bl = false;
        boolean br = false;
        boolean bu = false;
        boolean bd = false;

        @Override
        public void keyReleased(KeyEvent e) {
            int keyCode = e.getKeyCode();
            switch (keyCode) {
                case KeyEvent.VK_LEFT:
                    bl = false;
                    break;
                case KeyEvent.VK_RIGHT:
                    br = false;
                    break;
                case KeyEvent.VK_UP:
                    bu = false;
                    break;
                case KeyEvent.VK_DOWN:
                    bd = false;
                    break;
                case KeyEvent.VK_CONTROL:
                    t.fire();
                    break;
            }
            t.setMoving(false);
            setDir();
        }

        @Override
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();
            switch (keyCode) {
                case KeyEvent.VK_LEFT:
                    bl = true;
                    break;
                case KeyEvent.VK_RIGHT:
                    br = true;
                    break;
                case KeyEvent.VK_UP:
                    bu = true;
                    break;
                case KeyEvent.VK_DOWN:
                    bd = true;
                    break;
            }
            t.setMoving(true);
            setDir();
        }

        private void setDir() {
            if (!(bl || br || bu || bd)) {
                t.setMoving(false);
            }
            if (bl) t.setDir(Dir.LEFT);
            if (br) t.setDir(Dir.RIGHT);
            if (bu) t.setDir(Dir.UP);
            if (bd) t.setDir(Dir.DOWN);
        }
    }

    // 双缓冲 防止闪烁 （mac不会闪烁）
    Image offScreenImage = null;

    // update 在 repaint 之前执行
    @Override
    public void update(Graphics g) {
        if (offScreenImage == null) {
            offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
        }
        Graphics gOffScreen = offScreenImage.getGraphics();
        Color c = gOffScreen.getColor();
        gOffScreen.setColor(Color.BLACK);
        gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
        gOffScreen.setColor(c);
        paint(gOffScreen);
        g.drawImage(offScreenImage, 0, 0, null);
    }
}
